package com.gitee.wsl.net.ssdp.message

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.net.InetAddress
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

/**
 * Device or service update message
 * Used to validate provided fields and stringify data
 */
@Serializable
data class Update(
    val location: String,
    val usn: String,
    val bootId: Int,
    val configId: Int,
    val searchPort: Int?,
    val nextBootId: Int,
    @Serializable(with = InetAddressSerializer::class)
    val inetAddr: InetAddress?
){
    companion object{
        fun fromSsdpMessage(message: SsdpMessage): Update = Update(
            message.getRequiredHeader(Headers.Location),
            message.getRequiredHeader(Headers.UniqueServiceName),
            message.getRequiredHeader(Headers.BootId).toInt(),
            message.getRequiredHeader(Headers.ConfigId).toInt(),
            message.getHeader(Headers.SearchPort)?.toInt(),
            message.getRequiredHeader(Headers.NextBootId).toInt(),
            message.address
        )
    }
    override fun toString() = Json.encodeToString(this)
}

object InetAddressSerializer : KSerializer<InetAddress> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InetAddress", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: InetAddress) {
        encoder.encodeString(value.hostAddress)
    }

    override fun deserialize(decoder: Decoder): InetAddress {
        return InetAddress.getByName(decoder.decodeString())
    }
}